package applet;

import java.applet.Applet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.SwingUtilities;

import kb.DescriptionLogicsKB;

import utils.FontColor;
import utils.parser.Creator;
import utils.parser.Parser;
import utils.exception.SyntaxParsingException;

import algebra.query.ObjectQuery;
import algebra.query.pd.ProjDesc;
import algebra.visitors.AlgebraicOPEvaluator;
import utils.io.LoadWebFile;

import entities.assertion.ConceptAssertion;
import entities.concept.AndConcept;
import entities.concept.Concept;
import entities.concept.ExistsConcept;

public class ParamParser extends Applet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String concept;
	private String pd;
	private Concept parsedC;
	private ProjDesc parsedPd;
	private DescriptionLogicsKB kb;
	private int[] kbstat; // # of instances, concept assertions, role
							// assertions, axioms.
	private static boolean TEST = false;

	public void init() {
		try {
			SwingUtilities.invokeAndWait(new Runnable() {
				public void run() {
					kbstat = new int[4];
					if (TEST) {
						setParams("Student",
								"(pd-and (pd-feature name) (pd-feature age) )");
						parseParams();
						parseTargetKB("http://localhost/system/kb/sample.kbox");
						generateAndEvalQuery();
					}

				}
			});
		} catch (Exception e) {
			System.err.println("Getting paramters failed.");
		}

	}

	public int[] getKBStat() {
		return this.kbstat;
	}

	public boolean parseTargetKB(String url) {
		// not a query file
		LoadWebFile loader;
		if (TEST) {
			loader = new LoadWebFile(url, false);
		} else {
			loader = new LoadWebFile(getCodeBase() + url, false);
		}

		boolean getfile = loader.resolveFile();
		if (!getfile) {
			// failed to get a file
			return false;
		}
		this.kb = loader.getKB();
		// set stat info
		this.kbstat[0] = this.kb.getKBStat().getTotalInstances();
		this.kbstat[1] = this.kb.getKBStat().getNumCA();
		this.kbstat[2] = this.kb.getKBStat().getNumRA();
		this.kbstat[3] = this.kb.getKBStat().getNumAx();
		return true;
	}

	public Concept getParsedConcept() {
		return this.parsedC;
	}

	public ProjDesc getParsedPd() {
		return this.parsedPd;
	}

	public void setParams(String C, String PD) {
		this.concept = C;
		this.pd = PD;
	}

	// private void getParams() {
	// concept = this.getParameter("C");
	// pd = this.getParameter("PD");
	// }

	public boolean parseParams() {
		if (this.concept != null) {
			try {
				this.parsedC = Parser
						.conParser(Parser
								.getListOfTokensFromTokenizer(this.concept),
								kb);
			} catch (SyntaxParsingException e) {
				return false;
			}
		}
		if (this.pd != null) {
			try {
				this.parsedPd = Creator.createProjDesc(Parser
						.getListOfTokensFromTokenizer(this.pd), kb);
			} catch (SyntaxParsingException e) {
				return false;
			}
		}
		return true;
	}

	public String generateAndEvalQuery() {
		ObjectQuery pq = new ObjectQuery(this.parsedC, this.parsedPd);
		AlgebraicOPEvaluator eval = new AlgebraicOPEvaluator();
		List<ConceptAssertion> res = null;
		try {
			res = pq.translateAsExpression(kb).acceptVisitor(eval);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// /System.out.println(this.kbstat[0]);
		return analyzeResults(res);
	}

	private String analyzeResults(List<ConceptAssertion> res) {
		int assertionSize = 20;
		StringBuilder sb = new StringBuilder(res.size() * assertionSize);
		// String mystring ="";
		// sort CAs
		Collections.sort(res, new Comparator<ConceptAssertion>() {
			public int compare(ConceptAssertion o1, ConceptAssertion o2) {
				return o1.getIndividual().compareTo(o2.getIndividual());
			}
		});
		//
		for (int j = 0; j < res.size(); j++) {
			ConceptAssertion ca = res.get(j);
			String ret = "<ul STYLE=\"list-style-type:none; font-style: italic;\">"
					+ "<img src=\"images/instance.gif\" style=\"vertical-align:middle;\"/> "
					+ "<span style=\" color:"
					+ instancecolor
					+ "\">"
					+ ca.getIndividual() + "</span> : ";
			Concept c = ca.getConcept();
			ret += analyzeConcept(c) + "</ul>";
			sb.append(ret + "*");
			// mystring += ret+"*";
			if (TEST) {
				System.out.println(ret + "\n\n");
			}
		}
		return sb.toString();
	}

	private String instancecolor = FontColor.randomDarkRedColorCode();
	private String conceptcolor = FontColor.randomDarkBlueColorCode();
	private String rolecolor = FontColor.randomVioletColorCode();

	// represent a concept in a list form for display
	private String analyzeConcept(Concept C) {
		// String s = "";
		StringBuilder sb = new StringBuilder();
		if (C instanceof ExistsConcept) {
			ExistsConcept ec = (ExistsConcept) C;
			sb.append("<ul STYLE=\"list-style-type:none\";> ");
			sb.append("<img src=\"images/exists.gif\" style=\"vertical-align:middle;\"/>");
			sb.append("<span style=\" color:" + rolecolor + "\"> "
					+ ec.getRole() + "</span>");
			sb.append(analyzeConcept(ec.getFiller()) + "</ul>");
		} else if (C instanceof AndConcept) {
			AndConcept ac = (AndConcept) C;
			// s += "<ul>";
			List<Concept> sorts = new ArrayList<Concept>(ac.getConceptSet());
			Collections.sort(sorts, new Comparator<Concept>() {
				public int compare(Concept o1, Concept o2) {
					return o1.toString().compareTo(o2.toString());
				}
			});
			//
			for (int i = 0; i < sorts.size(); i++) {
				sb.append(analyzeConcept(sorts.get(i)));
			}
			// s += "</ul>";
		} else {
			sb.append("<li style = \" margin-left:1em; ");
			sb.append(" color:" + conceptcolor + ";\"> ");
			sb.append("<img src=\"images/concept.gif\" style=\"vertical-align:middle;\" /> ");
			sb.append(C.toString() + "</li>");
		}
		return sb.toString();
	}

	// determine if the two params can be parsed
	public void start() {
		// this.parseParams();
	}

}
